﻿using Colorful.Furniture.CommonDto;
using Colorful.Furniture.Extensions;
using Colorful.Furniture.Wrappers;
using FreeSql;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Colorful.Furniture.Enum;
using Volo.Abp;
using Volo.Abp.Application.Services;
using Volo.Abp.Users;
using Newtonsoft.Json;
using Colorful.Furniture.PermissionManagement;
using Microsoft.AspNetCore.Authorization;
using Volo.Abp.Auditing;

namespace Colorful.Furniture.ErpCustomerManagement;

/// <summary>
/// 客户服务
/// </summary>
[Authorize]
public class CustomerAppService : ApplicationService
{
    private readonly IBaseRepository<Customer> _customerRepository;
    private readonly IBaseRepository<CustomerLog> _customerLogRepository;
    private readonly IFreeSql _freeSql;
    private readonly CurrentUser _currentUser;
    private readonly ManagerAppService _managerAppService;
    private readonly IBaseRepository<SysManager> _sysManagerRepository;

    public CustomerAppService(
        IBaseRepository<Customer> customerRepository,
        IBaseRepository<CustomerLog> customerLogRepository,
        IFreeSql freeSql,
        CurrentUser currentUser,
        ManagerAppService managerAppService,
        IBaseRepository<SysManager> sysManagerRepository
    )
    {
        _customerRepository = customerRepository;
        _customerLogRepository = customerLogRepository;
        _freeSql = freeSql;
        _currentUser = currentUser;
        _managerAppService = managerAppService;
        _sysManagerRepository = sysManagerRepository;
    }


    /// <summary>
    ///  客户列表分页
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisableAuditing]
    public async Task<PageResponseWrapper<List<CustomerPagedOutputDto>>> PostPagedAsync([FromBody] CustomerInputDto input)
    {
        var query = _customerRepository
            .Where(x => !x.IsDeleted)
            .WhereIf(!string.IsNullOrWhiteSpace(input.Keyword), x => x.Name.Contains(input.Keyword) || x.Code.ToString().Contains(input.Keyword))
            .WhereIf(input.Status != null, x => x.Status == input.Status)
            .DisableGlobalFilter("SoftDelete");

        var sumItem = await query
            .ToAggregateAsync((x) => new
            {
                SumPrice = x.Sum(x.Key.Price),
                SumCreditPrice = x.Sum(x.Key.CreditPrice)
            });

        var list = await query
            .OrderByDescending(x => x.Sort)
            .OrderByDescending(x => x.AddTime) //按照创建时间倒序
            .OrderByDescending(x => x.Status) //按照启用禁用倒序
            .Count(out var pageTotalCount)
            .Page(input.PageIndex, input.PageSize)
            .ToListAsync(x => new CustomerPagedOutputDto());

        return new PageResponseWrapper<List<CustomerPagedOutputDto>, object>
        {
            Total = pageTotalCount,
            Items = list,
            SumItems = new { sumItem.SumPrice, sumItem.SumCreditPrice }
        };

    }


    /// <summary>
    ///  获取详情
    /// </summary>
    /// <returns></returns>
    [DisableAuditing]
    public async Task<CustomerDetailOutputDto> GetDetailAsync(Guid id)
    {
        var model = await _customerRepository
            .Where(x => x.Id == id)
            .ToOneAsync(x => new CustomerDetailOutputDto());

        return model;
    }


    /// <summary>
    ///  批量逻辑删除
    /// </summary>
    /// <param name="idList">ID集合</param>
    /// <returns></returns> 
    public async Task<bool> DeleteBatchByIdAsync([FromBody] List<Guid?> idList)
    {
        await _freeSql.Update<Customer>()
            .Set(x => x.IsDeleted, true)
            .Set(x => x.DeletedTime, DateTime.Now)
            .Where(x => idList.Contains(x.Id))
            .ExecuteAffrowsAsync();

        return true;
    }


    /// <summary>
    ///  批量启用或禁用客户信息
    /// </summary>
    /// <returns></returns>]
    public async Task UpdateStatusAsync([FromBody] CustomerStatesInputDto input)
    {
        // 禁用
        if (input.StateType == 0)
        {
            await _freeSql.Update<Customer>()
                .Set(x => x.Status, 0)
                .Where(x => input.Id.Contains(x.Id))
                .ExecuteAffrowsAsync();
        }
        else // 启用
        {
            await _freeSql.Update<Customer>()
                .Set(x => x.Status, 1)
                .Where(x => input.Id.Contains(x.Id))
                .ExecuteAffrowsAsync();
        }
    }


    /// <summary>
    ///  获取客户选项列表
    /// </summary>
    /// <param name="name">客户名字</param>
    /// <param name="type">类别</param>
    /// <returns></returns>
    public async Task<List<OptionOutputDto<Guid, CustomerOptionDataOutputDto>>> GetOptionListByNameAsync(string name, int type)
    {
        var list = await _freeSql.Select<Customer>()
            .WhereIf(!string.IsNullOrWhiteSpace(name), x => x.Name.Contains(name))
            .Where(x => x.Status == 1)
            .OrderByDescending(x => x.Sort)
            .OrderByDescending(x => x.AddTime)
            .ToListAsync(x => new OptionOutputDto<Guid, CustomerOptionDataOutputDto>
            {
                Label = x.Name,
                Value = x.Id,
                Data = new CustomerOptionDataOutputDto
                {
                    //Address = $"{x.DeliveryCityText} {x.DeliveryAddress}",
                    ContactName = x.Name,
                    ContactPhone = x.Name
                }
            });

        return list;
    }


    /// <summary>
    ///  保存客户信息
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    public async Task<Guid?> SaveAsync([FromBody] SaveCustomerInputDto input)
    {
        //修改
        if (!input.Id.IsNull())
        {
            var customerInfo = await _freeSql.Select<Customer>()
                .Where(x => x.Id == input.Id).FirstAsync();
            if (customerInfo == null)
                throw new UserFriendlyException("客户信息不存在，请联系管理员！");

            // 日志记录
            var customerLogUpdateInfo = new CustomerLog()
            {
                Id = new Guid(),
                CustomerId = input.Id,
                ChangePrice = 0,
                BeforePrice = customerInfo.Price,
                AfterPrice = input.Price,
                BeforeCreditPrice = customerInfo.CreditPriceInitial,
                AfterCreditPrice = input.CreditPriceInitial,
                Operator = CurrentUser.Name,
                OperatorNo = CurrentUser.UserName,
                OperatorType = !input.Id.HasValue ? EnumOperatorType.新增 : EnumOperatorType.修改,
                OperatorTime = Clock.Now,
                LogContent = $"【{CurrentUser.Name}】执行【修改】客户信息 - 客户名称：【{customerInfo.Name}】 ；客户编码：【{customerInfo.Code}】 ；" +
                             $"账户余额：{customerInfo.Price} → {input.Price} ；授信额度：{customerInfo.CreditPriceInitial} → {input.CreditPriceInitial}  ； \r\n {input.Remark}",
                RequestJson = JsonConvert.SerializeObject(input, Formatting.None),
            };

            var customers = ObjectMapper.Map(input, customerInfo);

            await _freeSql.Update<Customer>()
                .SetSource(customers)
                .ExecuteAffrowsAsync();

            await _customerLogRepository.InsertAsync(customerLogUpdateInfo);

            return input.Id;
        }

        //新增
        var customerInsert = ObjectMapper.Map<SaveCustomerInputDto, Customer>(input);
        var customerCode = SetCustomerCode();
        customerInsert.Key = Md5Encrypt.Md5Encrypt32Small(customerCode.ToString() + customerInsert.Id.ToString());
        customerInsert.Price = 0;
        customerInsert.Status = 1;
        customerInsert.FrozenAmount = 0;
        customerInsert.CreditPrice = 0;
        customerInsert.Code = customerCode;
        await _freeSql
            .Insert(customerInsert)
            .ExecuteAffrowsAsync();

        // 日志记录
        var customerLogAddInfo = new CustomerLog()
        {
            Id = new Guid(),
            CustomerId = customerInsert.Id,
            ChangePrice = 0,
            BeforePrice = 0,
            AfterPrice = 0,
            BeforeCreditPrice = input.CreditPriceInitial,
            AfterCreditPrice = input.CreditPriceInitial,
            Operator = CurrentUser.Name,
            OperatorNo = CurrentUser.UserName,
            OperatorType = !input.Id.HasValue ? EnumOperatorType.新增 : EnumOperatorType.修改,
            OperatorTime = Clock.Now,
            LogContent = $"【{CurrentUser.Name}】执行【创建】客户信息 - 客户名称：【{input.Name}】 ；客户编码：【{customerCode}】 ；账户余额：0 ；授信额度：{input.CreditPriceInitial}",
            RequestJson = JsonConvert.SerializeObject(input, Formatting.None),
        };

        await _customerLogRepository.InsertAsync(customerLogAddInfo);

        return customerInsert.Id;
    }


    /// <summary>
    /// 生成客户编号
    /// </summary>
    [RemoteService(false)]
    [DisableAuditing]
    public int SetCustomerCode()
    {
        //获得当前最大编号
        var orderInfo = _freeSql.Select<Customer>()
            .DisableGlobalFilter("SoftDelete")
            .OrderByDescending(x => x.AddTime)
            .FirstAsync();

        var number = 101;
        if (orderInfo.Result != null)
        {
            number = Convert.ToInt32(orderInfo.Result.Code) + 1;
        }
        return number;
    }

}

